package IC.AST.SemanticAnalysis;

import IC.AST.*;
import IC.Error.ErrorStack;
import IC.Error.ErrorStringIntervaled;
import IC.Error.Error.ErrorType;

class CheckBreakContinueVisitor extends UnreachableCodeVisitor
{
	private int _whileDepth;

	
	public Object Visit(Program rootNode)
	{
		_whileDepth = 0;
		return super.Visit(rootNode);
	}
	
	public Object Visit(Method node)
	{
		_funcName = node.GetID();
		return VisitSons(node);
	}
	
	public Object Visit(ContinueStatement node)
	{
		if (_whileDepth == 0)
			return AddBreakContinueError("continue", node.GetInterval());
		return true;
	}
	
	public Object Visit(BreakStatement node)
	{
		if (_whileDepth == 0)
			return AddBreakContinueError("break", node.GetInterval());
		return true;
	}
	
	private Object AddBreakContinueError(String errorMessage, Interval interval)
	{
		return ErrorStack.Push(new ErrorStringIntervaled(ErrorType.Semantic, 
				String.format(
					"Can't use %s not in s while statement, in function '%s' in class '%s'", 
					errorMessage, _funcName, _classID), 
				interval));
	}
	
	public Object Visit(WhileStatement node)
	{
		_whileDepth++;
		VisitSons(node);
		_whileDepth--;
		return null;
	}
	
	public Object Visit(ScopeStatement node) 
	{
		if (_whileDepth != 0)
			return CheckForUnreachableCode(node, "break/continue");
		else
			return VisitSons(node);
	}
}
